package com.windgo.config;

import com.windgo.config.realm.CustomRealm;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.Arrays;
import java.util.LinkedHashMap;

/**
 * 保证跨域场景下session一致问题。
 *
 * @author 张林浩
 * @since 2022/10/11 21:36
 */
@Configuration
public class ShiroConfiguration {

    /**
     * ShiroFilter
     *
     * @return
     */
    @Bean
    public ShiroFilterFactoryBean shiroFilter(DefaultWebSecurityManager securityManager) {

        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        shiroFilterFactoryBean.setSecurityManager(securityManager);

        //建立URL和filter之间的映射关系。
        //保证值是有序的
        LinkedHashMap<String, String> filterChainDefinitionMap = new LinkedHashMap<>();
        // /admin/auth/login这个url对应着 anon Filter → 匿名Filter  Filter的值是固定的，anon\authc、perms
        // anon（匿名） 任何用户发送的请求都能访问，
        // authc 经过认证的请求可访问，否则重定向，authc.loginUrl
        //logout回话结束
        //key 对应的是请求入了，value对应的是filter的名称。

        //通常顺序是anon authc perms,anon 写在authc之后，authc会失效

        //TODO 测试中
        filterChainDefinitionMap.put("/admin/auth/login", "anon");
        filterChainDefinitionMap.put("/admin/auth/info", "anon");

        filterChainDefinitionMap.put("/admin/auth/noAuthc","anon");//TODO 需要响应一段JSON数据
        filterChainDefinitionMap.put("/admin/auth/logout","anon");
        filterChainDefinitionMap.put("/admin/dashboard","authc");


        //filterChainDefinitionMap.put("/admin/topic/**","authc");//TODO @RequiresPermission
        //filterChainDefinitionMap.put("/admin/admin/**","authc");//TODO @RequiresPermission
        //filterChainDefinitionMap.put("/admin/log/list","authc");//TODO @RequiresPermission


        // filterChainDefinitionMap.put("/admin/storage/**","authc");//TODO @RequiresPermission
        // filterChainDefinitionMap.put("/wx/storage/fetch/**","anon");//TODO @RequiresPermission
        // filterChainDefinitionMap.put("/admin/goods/**","authc");//TODO @RequiresPermission
        // filterChainDefinitionMap.put("/admin/comment/**","authc");//TODO @RequiresPermission
        // filterChainDefinitionMap.put("/admin/config/**","authc");//TODO @RequiresPermission
        // filterChainDefinitionMap.put("/admin/stat/**","authc");//TODO @RequiresPermission
        // filterChainDefinitionMap.put("/admin/role/**","authc");//TODO @RequiresPermission
        //
        // filterChainDefinitionMap.put("/admin/issue/**","authc");//TODO @RequiresPermission
        // filterChainDefinitionMap.put("/admin/region/**","authc");//TODO @RequiresPermission
        //
        //
        // filterChainDefinitionMap.put("/admin/ad/**","anon");
        // filterChainDefinitionMap.put("/admin/coupon/**","anon");
        //
        // filterChainDefinitionMap.put("/admin/config/**","anon");
        // filterChainDefinitionMap.put("/admin/order/**","anon");
        // filterChainDefinitionMap.put("/admin/stat/**","anon");
        // filterChainDefinitionMap.put("/admin/role/**","anon");


        // // TODO:10月12日23点08分 mabai增加
        // filterChainDefinitionMap.put("/admin/user/list", "anon");
        // // TODO:10月13日13点53分 mabai增加
        // filterChainDefinitionMap.put("/admin/category/**", "anon");
        //
        // filterChainDefinitionMap.put("/admin/address/**","anon");
        // filterChainDefinitionMap.put("/admin/collect/**","anon");
        // filterChainDefinitionMap.put("/admin/footprint/**","anon");
        // filterChainDefinitionMap.put("/admin/history/**","anon");
        // filterChainDefinitionMap.put("/admin/feedback/**","anon");
        // filterChainDefinitionMap.put("/admin/brand/**","anon");
        // filterChainDefinitionMap.put("/admin/keyword/**","anon");


        // admin开头的请求，都要通过认证Filter
        filterChainDefinitionMap.put("/admin/**", "authc");//以subject作为入口

        //TODO 这是个例子

        // 权限的配置，可以将url和对应的权限建立映射关系
        // 还可以通过注解的方式来建议url和权限之间的映射关系 → Advisor、@RequiresPermission（Handler方法上）

        // url和handler方法对应、权限和Handler方法对应 → url和权限对应
        //使用aspectj做handler和URL的耦合
        //TODO 可以在handler方法上加@RequestPermission()

        //@RequiresPermission("/admin/admin/list", "perms[admin:admin:list]")
        //filterChainDefinitionMap.put("/admin/admin/list", "perms[admin:admin:list]");

        //如果访问某个请求的时候，该请求对应的filter是authc，如果没有通过这个filter则说明没有通过这个filter说明没有权限
        //shiro做重定向，默认地址是/login.jsp,可以使用方法修改重定向地址
         shiroFilterFactoryBean.setLoginUrl("/admin/auth/noAuthc");
       // shiroFilterFactoryBean.setLoginUrl("/admin/auth/logout");

        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);

        return shiroFilterFactoryBean;

    }

    /**
     * SecurityManager
     */
    @Bean
    public DefaultWebSecurityManager securityManager(CustomRealm realm,
                                                     DefaultWebSessionManager sessionManager) {
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        //给securityManager\默认的认证器和默认的授权器都设置realms
        securityManager.setRealms(Arrays.asList(realm));
        securityManager.setSessionManager(sessionManager);
        return securityManager;
    }

    @Bean
    public DefaultWebSessionManager sessionManager() {
        return new MarketSessionManager();
    }




    // 用到AspectJ → 使用注解的方式，将权限和url绑定起来
    //通知器
    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(DefaultWebSecurityManager securityManager) {
        AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
        authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
        return authorizationAttributeSourceAdvisor;
    }


}

